home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 276-300 / disk_280 / graph / coords.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  6KB  |  210 lines

  1. /*
  2.  *                 GRAPH, Version 1.00 - 4 August 1989
  3.  *
  4.  *            Copyright 1989, David Gay. All Rights Reserved.
  5.  *            This software is freely redistrubatable.
  6.  */
  7.  
  8. /* Set up a coordinate system in a Rastport */
  9. /* Copyright 1989, David Gay */
  10. #include <exec/types.h>
  11. #include <graphics/regions.h>
  12. #include <intuition/intuition.h>
  13. #include <proto/graphics.h>
  14. #include <proto/layers.h>
  15.  
  16. #include <limits.h>
  17. #include <math.h>
  18.  
  19. #include "coords.h"
  20. #include "tracker.h"
  21.  
  22. extern int _FPERR;
  23.  
  24. /* Actual structure used */
  25. struct RWin {
  26.     struct RWindow rw;
  27.     double xmin, xscale, ymin, yscale;
  28.     double xoffset, yoffset;
  29.     struct Region *clip, *oldRegion;
  30.     int lostpos;
  31. };
  32.  
  33. /*-------------------------------------------------------------------------*/
  34. /*                            RWindow definition                           */
  35. /*-------------------------------------------------------------------------*/
  36.  
  37. /* convert double to integer, round down. cf floor */
  38. long ftol(double x)
  39. {
  40.     if (x >= 0) return (long)x;
  41.     else return (long)floor(x);
  42. }
  43.  
  44. /* Do Move/Draw style operation func, checking for overflow, etc */
  45. static void rdo_RWin(struct RWin *this, void (*func)(struct RastPort *rp, long
  46. sx, long sy), double x, double y)
  47. {
  48.     double sx, sy;
  49.  
  50.     if (this->lostpos) func = Move;
  51.  
  52.     _FPERR = 0;
  53.     sx = this->rw.sx((struct RWindow *)this, x);
  54.     sy = this->rw.sy((struct RWIndow *)this, y);
  55.     /* Move, Draw only accept shorts */
  56.     this->lostpos = (_FPERR != 0 || fabs(sx) > SHRT_MAX || fabs(sy) > SHRT_MAX)
  57. ;
  58.  
  59.     if (!this->lostpos) func(this->rw.rp, ftol(sx), ftol(sy));
  60. }
  61.  
  62. /* The various conversion routines, to/from ints, for lin orr log scales, x or
  63. y ax */
  64. static double sx_lin(struct RWin *this, double x)
  65. {
  66.     return (x - this->xmin) * this->xscale + this->xoffset;
  67. }
  68.  
  69. static double sx_log(struct RWin *this, double x)
  70. {
  71.     return (log10(x) - this->xmin) * this->xscale + this->xoffset;
  72. }
  73.  
  74. static double sy_lin(struct RWin *this, double y)
  75. {
  76.     return (y - this->ymin) * this->yscale + this->yoffset;
  77. }
  78.  
  79. static double sy_log(struct RWin *this, double y)
  80. {
  81.     return (log10(y) - this->ymin) * this->yscale + this->yoffset;
  82. }
  83.  
  84. static double x_lin(struct RWin *this, long sx)
  85. {
  86.     return (sx - this->xoffset) / this->xscale + this->xmin;
  87. }
  88.  
  89. static double x_log(struct RWin *this, long sx)
  90. {
  91.     return pow(10.0, (sx - this->xoffset) / this->xscale + this->xmin);
  92. }
  93.  
  94. static double y_lin(struct RWin *this, long sy)
  95. {
  96.     return (sy - this->yoffset) / this->yscale + this->ymin;
  97. }
  98.  
  99. static double y_log(struct RWin *this, long sy)
  100. {
  101.     return pow(10.0, (sy - this->yoffset) / this->yscale + this->ymin);
  102. }
  103.  
  104. /* Delete a member of this class */
  105. static void delete_RWin(struct RWin *this)
  106. {
  107.     if (this->clip)
  108.     {
  109.         InstallClipRegion(this->rw.rp->Layer, this->oldRegion);
  110.         DisposeRegion(this->clip);
  111.     }
  112.     FreeMem(this, sizeof(struct RWin));
  113. }
  114.  
  115. /* Create a coordinate system in Rastport rp (w by h pixels),
  116.    {...}offset : offset in rp at which coords starts (normally > 0)
  117.    {x,y}{min,max} : limits for coords
  118.    logx, logy : logarithmic scale ?
  119.    clip : setup clipping to {...}offset boundaries ?
  120. */
  121. struct RWindow *new_RWindow(struct RastPort *rp, long w, long h,
  122.                             long leftoffset, long bottomoffset, long rightoffse
  123. t, long topoffset,
  124.                             double xmin, double ymin, double xmax, double ymax,
  125.      
  126.                             long logx, long logy, long clip)
  127. {
  128.     long width, height;
  129.     struct Rectangle rect;
  130.     struct Region *r;
  131.     struct RWin *this = AllocMem(sizeof(struct RWin), 0L);
  132.  
  133.     if (this)
  134.     {
  135.         /* Setup class methods, and private data */
  136.         this->rw.delete = (void *)delete_RWin;
  137.         this->rw.rdo = (void *)rdo_RWin;
  138.         /* Setup scaling */
  139.         this->rw.rp = rp;
  140.         this->xoffset = leftoffset;
  141.         this->yoffset = h - bottomoffset - 1;
  142.         width = w - leftoffset - rightoffset - 1;
  143.         height = h - bottomoffset - topoffset - 1;
  144.         if (logx)
  145.         {
  146.             this->xmin = log10(xmin);
  147.             this->xscale = width / (log10(xmax) - this->xmin);
  148.             this->rw.sx = (void *)sx_log;
  149.             this->rw.x = (void *)x_log;
  150.         }
  151.         else
  152.         {
  153.             this->xmin = xmin;
  154.             this->xscale = width / (xmax - this->xmin);
  155.             this->rw.sx = (void *)sx_lin;
  156.             this->rw.x = (void *)x_lin;
  157.         }
  158.         if (logy)
  159.         {
  160.             this->ymin = log10(ymin);
  161.             this->yscale = height / (this->ymin - log10(ymax));
  162.             this->rw.sy = (void *)sy_log;
  163.             this->rw.y = (void *)y_log;
  164.         }
  165.         else
  166.         {
  167.             this->ymin = ymin;
  168.             this->yscale = height / (this->ymin - ymax);
  169.             this->rw.sy = (void *)sy_lin;
  170.             this->rw.y = (void *)y_lin;
  171.         }
  172.  
  173.         if (clip)
  174.         {
  175.             /* Setup clipping */
  176.             if (r = NewRegion())
  177.             {
  178.                 rect.MinX = leftoffset;
  179.                 rect.MaxX = w - rightoffset - 1;
  180.                 rect.MinY = topoffset;
  181.                 rect.MaxY = h - bottomoffset - 1;
  182.                 if (OrRectRegion(r, &rect))
  183.                 {
  184.                     this->clip = r;
  185.  
  186. /* Remark: Due to a bug(?) in InstallClipRegion, make sure that the currently
  187.   installed region when EndRefresh is called is not NULL (trashed windows
  188.   otherwise...). */
  189.                     this->oldRegion = InstallClipRegion(rp->Layer, r);
  190.                 }
  191.                 else
  192.                 {
  193.                     DisposeRegion(r);
  194.                     r = NULL;
  195.                 }
  196.             }
  197.             if (!r)
  198.             {
  199.                 FreeMem(this, sizeof(struct RWin));
  200.                 this = NULL;
  201.             }
  202.         }
  203.         else
  204.             this->clip = NULL;
  205.     }
  206.     /* Return the newly allocated instance */
  207.     return (struct RWindow *)this;
  208. }
  209.  
  210.